/*
 * Dcm_UDS0x31.c
 *
 *  Created on: 2018-1-16
 *      Author: Shute
 */
#include "UDS.h"


/****************************************************************
                 UDS:RoutineControl (31 hex) service
 ***************************************************************/
#if(STD_ON == DCM_UDS_SERVICE0X31_ENABLED)

static FUNC(Std_ReturnType, DCM_CODE)Dcm_RCConditonCheck(
		uint8   ProtocolCtrlId);


static FUNC(Std_ReturnType, DCM_CODE)Dcm_UdsSesAndSecCheck(
		uint8 ProtocolCtrlId,
		P2CONST(Dcm_DspCommonAuthorizationType, AUTOMATIC, DCM_APPL_CONST)  pDspCommonAuthorization);

static FUNC(Std_ReturnType, DCM_CODE)Dcm_UdsRCSesAndSecCheck(
		uint8 ProtocolCtrlId,
		uint8 RoutineCfgIdx);



static FUNC(uint8, DCM_CODE)Dcm_UdsRCStartRoutine(
		uint8  MsgCtrlId,
		uint8  RoutineCfgId,
		uint16 Offset,
		P2VAR(Std_ReturnType, AUTOMATIC, AUTOMATIC) Ret,
		P2VAR(Dcm_NegativeResponseCodeType, AUTOMATIC, AUTOMATIC)ErrorCode);


static FUNC(uint8, DCM_CODE)Dcm_UdsRCStopRoutine(
		uint8  MsgCtrlId,
		uint8  RoutineCfgId,
		uint16 Offset,
		P2VAR(Std_ReturnType, AUTOMATIC, AUTOMATIC) Ret,
		P2VAR(Dcm_NegativeResponseCodeType, AUTOMATIC, AUTOMATIC) ErrorCode);

static FUNC(uint8, DCM_CODE)Dcm_UdsRCReqRoutineResult(
		uint8   MsgCtrlId,
		uint8   RoutineCfgId,
		uint16  Offset,
		P2VAR(Std_ReturnType, AUTOMATIC, AUTOMATIC) Ret,
		P2VAR(Dcm_NegativeResponseCodeType, AUTOMATIC, AUTOMATIC) ErrorCode);

static FUNC(void, DCM_CODE)Dcm_UdsRCSendMsg(
		uint8   ProtocolCtrlId,
		uint8   MsgCtrlId,
		uint8   ResLen,
		uint16  routineId,
		uint16  Offset,
		uint8   SubFunction,
		Std_ReturnType  Ret,
		Dcm_NegativeResponseCodeType  ErrorCode);

/********************************/
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(Std_ReturnType, DCM_CODE)Dcm_RCConditonCheck(
		uint8   ProtocolCtrlId)
{
	Std_ReturnType  Ret;

	#if(STD_ON == DCM_SESSION_FUNC_ENABLED)
	/*session check,check whether the current session supports the request service*/
	Ret = DsdInternal_SesCheck(ProtocolCtrlId, SID_ROUTINE_CONTROL);
	if(E_NOT_OK == Ret)
	{
		/****@req DCM-FUNR-073[DCM211]****/
		/*the current session does not support the request service,send NRC = 0x7F*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_SERVICENOTSUPPORTEDINACTIVESESSION);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}
	#endif
	/*************************************************/
	#if(STD_ON == DCM_SECURITY_FUNC_ENABLED)
	/*security check,check whether the current security supports the request service*/
	Ret = DsdInternal_SecurityCheck(ProtocolCtrlId, SID_ROUTINE_CONTROL);
	if (E_NOT_OK == Ret)
	{
		/****@req DCM-FUNR-074[DCM217]****/
		/*the current security does not support the request service,send NRC = 0x33*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_SECURITYACCESSDENIED);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}
	#endif

	return E_OK;
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"

/********************************/
#if(STD_ON == DCM_DSP_ROUTINE_FUNC_ENABLED)
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(Std_ReturnType, DCM_CODE)Dcm_UdsSesAndSecCheck(
		uint8 ProtocolCtrlId,
		P2CONST(Dcm_DspCommonAuthorizationType, AUTOMATIC, DCM_APPL_CONST)  pDspCommonAuthorization)
{
#if(  (STD_ON==DCM_SESSION_FUNC_ENABLED) ||(STD_ON == DCM_SECURITY_FUNC_ENABLED) )
	uint8   Index;
	boolean Flag;
#endif
#if(STD_ON == DCM_SESSION_FUNC_ENABLED)
	uint8   RoutineSesNum;
#endif
#if(STD_ON == DCM_SECURITY_FUNC_ENABLED)
	uint8   RoutineSecNum;
#endif

	Std_ReturnType  Ret = E_OK;

	#if(STD_ON == DCM_SESSION_FUNC_ENABLED)
	Flag = FALSE;
	RoutineSesNum = pDspCommonAuthorization->DcmDspCommonAuthorizationSessionRefNum;
	if (RoutineSesNum != 0u)
	{
        for (Index=0; (Index < RoutineSesNum) && (FALSE == Flag); Index++)
        {
            if (Dcm_MkCtrl.Dcm_ActiveSes
                    == pDspCommonAuthorization->DcmDspCommonAuthorizationSessionRef[Index])
            {
                Flag = TRUE;
            }
        }
        if (FALSE == Flag)
        {
            /*SWS_Dcm_00570*/
            (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_REQUESTOUTOFRANGE);
            DsdInternal_ProcessingDone(ProtocolCtrlId);
            return  E_NOT_OK;
        }
	}
	#endif

	/*************************************************/
	/*check security*/
	#if(STD_ON==DCM_SECURITY_FUNC_ENABLED)
	Flag = FALSE;
	RoutineSecNum =
	        pDspCommonAuthorization->DcmDspCommonAuthorizationSecurityLevelRefNum;
	if (RoutineSecNum != 0u)
	{
        for (Index = 0; (Index < RoutineSecNum) && (FALSE == Flag); Index++)
        {
            if (Dcm_MkCtrl.Dcm_ActiveSec
                    == pDspCommonAuthorization->DcmDspCommonAuthorizationSecurityLevelRef[Index])
            {
                Flag = TRUE;
            }
        }
        if(FALSE == Flag)
        {
            /*SWS_Dcm_00571*/
            /*the processing is not supported in current security level,send NRC 0x33*/
            (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_SECURITYACCESSDENIED);
            DsdInternal_ProcessingDone(ProtocolCtrlId);
            return  E_NOT_OK;
        }
	}
	#endif

	return Ret;
}

static FUNC(Std_ReturnType, DCM_CODE)Dcm_UdsRCSesAndSecCheck(
		uint8 ProtocolCtrlId,
		uint8 RoutineCfgIdx)
{
	P2CONST(Dcm_DspCommonAuthorizationType, AUTOMATIC, DCM_APPL_CONST)
	        pDspRoutineAuthorization;
	P2CONST(Dcm_DspCommonAuthorizationType, AUTOMATIC, DCM_APPL_CONST)
	    pDspStartRoutineAuthorization;
	P2CONST(Dcm_DspCommonAuthorizationType, AUTOMATIC, DCM_APPL_CONST)
	    pDspStopRoutineAuthorization;
	P2CONST(Dcm_DspCommonAuthorizationType, AUTOMATIC, DCM_APPL_CONST)
	    pDspRequestRoutineResultsAuthorization;

	Std_ReturnType  Ret = E_OK;

	pDspRoutineAuthorization = Dcm_DspCfg.pDcmDspRoutine[RoutineCfgIdx].
	        DcmDspCommonAuthorizationRef;
	if (pDspRoutineAuthorization != NULL_PTR)
	{
		Ret = Dcm_UdsSesAndSecCheck(ProtocolCtrlId, pDspRoutineAuthorization);
		if(E_OK != Ret)
		{
			return Ret;
		}
	}

	if (Dcm_DspCfg.pDcmDspRoutine[RoutineCfgIdx].DcmDspStartRoutine != NULL_PTR)
	{
		pDspStartRoutineAuthorization =
				Dcm_DspCfg.pDcmDspRoutine[RoutineCfgIdx].DcmDspStartRoutine->
				DcmDspStartRoutineCommonAuthorizationRef;
		if (pDspStartRoutineAuthorization != NULL_PTR)
		{
			Ret = Dcm_UdsSesAndSecCheck(ProtocolCtrlId, pDspStartRoutineAuthorization);
			if(E_OK != Ret)
			{
				return Ret;
			}
		}
	}

	if (Dcm_DspCfg.pDcmDspRoutine[RoutineCfgIdx].DcmDspStopRoutine != NULL_PTR)
	{
		pDspStopRoutineAuthorization =
				Dcm_DspCfg.pDcmDspRoutine[RoutineCfgIdx].DcmDspStopRoutine->
				DcmDspStopRoutineCommonAuthorizationRef;
		if (pDspStopRoutineAuthorization != NULL_PTR)
		{
			Ret = Dcm_UdsSesAndSecCheck(ProtocolCtrlId, pDspStopRoutineAuthorization);
			if(E_OK != Ret)
			{
				return Ret;
			}
		}
	}

	if (Dcm_DspCfg.pDcmDspRoutine[RoutineCfgIdx].DcmDspRequestRoutineResults != NULL_PTR)
	{
		pDspRequestRoutineResultsAuthorization =
				Dcm_DspCfg.pDcmDspRoutine[RoutineCfgIdx].DcmDspRequestRoutineResults->
				DcmDspRequestRoutineResultsCommonAuthorizationRef;
		if (pDspRequestRoutineResultsAuthorization != NULL_PTR)
		{
			Ret = Dcm_UdsSesAndSecCheck(ProtocolCtrlId, pDspRequestRoutineResultsAuthorization);
			if(E_OK != Ret)
			{
				return Ret;
			}
		}
	}
	if ((Dcm_DspCfg.pDcmDspRoutine[RoutineCfgIdx].DcmDspRequestRoutineResults == NULL_PTR)
	        && (Dcm_DspCfg.pDcmDspRoutine[RoutineCfgIdx].DcmDspStopRoutine == NULL_PTR)
	        &&(Dcm_DspCfg.pDcmDspRoutine[RoutineCfgIdx].DcmDspStartRoutine == NULL_PTR))
	{
		(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_CONDITIONSNOTCORRECT);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}

	return Ret;
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"
#endif

/********************************/
#if(STD_ON == DCM_DSP_ROUTINE_FUNC_ENABLED)
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(uint8, DCM_CODE)Dcm_UdsRCStartRoutine(
		uint8  MsgCtrlId,
		uint8  RoutineCfgId,
		uint16 Offset,
		P2VAR(Std_ReturnType, AUTOMATIC, AUTOMATIC) Ret,
		P2VAR(Dcm_NegativeResponseCodeType, AUTOMATIC, AUTOMATIC)ErrorCode)
{
	uint8   ReqLen = 0;
	uint8   ResLen = 0;
	uint8   RoutineInSignalNum;
	uint8   RoutineOutSignalNum;
	uint8   Index;
	Dcm_StartRoutineFncType   StartRoutineFnc;
	P2CONST(Dcm_DspStartRoutineType,TYPEDEF,DCM_CONST)   StartRoutine;
	P2VAR(uint8 ,AUTOMATIC ,DCM_VAR_NOINIT) pInbuffer;
	P2VAR(uint8 ,AUTOMATIC ,DCM_VAR_NOINIT) pOutBuffer;

	StartRoutine = Dcm_DspCfg.pDcmDspRoutine[RoutineCfgId].DcmDspStartRoutine;
    if (NULL_PTR == StartRoutine)
    {
        /*StartRoutineFnc is NULL,send NRC 0x12*/
        *ErrorCode  = DCM_E_SUBFUNCTIONNOTSUPPORTED;
        *Ret = E_NOT_OK;
        return ResLen;
    }
    if (NULL_PTR != StartRoutine->DcmDspStartRoutineIn)
    {
    	RoutineInSignalNum = StartRoutine->DcmDspStartRoutineIn->RoutineInOutSignalNum;
    	for (Index = 0; Index < RoutineInSignalNum; Index++)
    	{
    		ReqLen = ReqLen +
    		     ((uint8)((StartRoutine->DcmDspStartRoutineIn->DcmDspRoutineInOutSignal[Index].
    		             DcmDspRoutineSignalLength + 7u) >> 3u));
    	}
    }
    else
    {
    	ReqLen = 0;
    }

    if (NULL_PTR != StartRoutine->DcmDspStartRoutineOut)
    {
		RoutineOutSignalNum = StartRoutine->DcmDspStartRoutineOut->RoutineInOutSignalNum;
		for (Index = 0; Index < RoutineOutSignalNum; Index++)
		{
			ResLen = ResLen + ((uint8)((StartRoutine->DcmDspStartRoutineOut->
					DcmDspRoutineInOutSignal[Index].DcmDspRoutineSignalLength + 7u)>> 3u));
		}
    }
    else
    {
    	ResLen = 0;
    }

	/*check the request message length*/
	if ((ReqLen + DCM_UDS0X31_REQ_DATA_MINLENGTH)
	        != ((uint8)Dcm_MsgCtrl[MsgCtrlId].MsgContext.ReqDataLen))
	{
		/*the request message length is not correct,send NRC 0x13*/
		*ErrorCode  = DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT;
		*Ret = E_NOT_OK;
		return ResLen;
	}

	StartRoutineFnc = StartRoutine->DcmDspStartRoutineFnc;
	if (NULL_PTR == StartRoutineFnc)
	{
		/*StartRoutineFnc is NULL,send NRC 0x31*/
		*ErrorCode  = DCM_E_REQUESTOUTOFRANGE;
		*Ret = E_NOT_OK;
		return ResLen;
	}

	pInbuffer  = NULL_PTR;
	if (0u != ReqLen)
	{
		pInbuffer = &Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[4];
	}
	pOutBuffer = NULL_PTR;
	if (0u != ResLen)
	{
		pOutBuffer = &Dcm_Channel[Offset + 4u];
	}
	*Ret = (*StartRoutineFnc)(pOutBuffer, pInbuffer, ErrorCode);

	if (E_OK == *Ret)
	{
		Dcm_RoutineControlState[RoutineCfgId] = DCM_DSP_ROUTINE_ON;
	}

	return ResLen;
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"
#endif

/********************************/
#if(STD_ON == DCM_DSP_ROUTINE_FUNC_ENABLED)
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(uint8, DCM_CODE)Dcm_UdsRCStopRoutine(
		uint8  MsgCtrlId,
		uint8  RoutineCfgId,
		uint16 Offset,
		P2VAR(Std_ReturnType, AUTOMATIC, AUTOMATIC) Ret,
		P2VAR(Dcm_NegativeResponseCodeType, AUTOMATIC, AUTOMATIC) ErrorCode)
{
	uint8   ReqLen = 0;
	uint8   ResLen = 0;
	uint8   RoutineInSignalNum;
	uint8   RoutineOutSignalNum;
	uint8   Index;
	P2CONST(Dcm_DspStopRoutineType,TYPEDEF,DCM_CONST)   StopRoutine;
	Dcm_StopRoutineFncType   StopRoutineFnc;
	P2VAR(uint8 ,AUTOMATIC ,DCM_VAR_NOINIT) pInbuffer;
	P2VAR(uint8 ,AUTOMATIC ,DCM_VAR_NOINIT) pOutBuffer;
    if (Dcm_DspCfg.pDcmDspRoutine[RoutineCfgId].DcmDspStopRoutine == NULL_PTR)
    {
        /*StopRoutineFnc is NULL,send NRC 0x12*/
        *ErrorCode  = DCM_E_SUBFUNCTIONNOTSUPPORTED;
        *Ret = E_NOT_OK;
        return ResLen;
	}

    StopRoutine = Dcm_DspCfg.pDcmDspRoutine[RoutineCfgId].DcmDspStopRoutine;
    if (StopRoutine->DcmDspStopRoutineIn != NULL_PTR)
    {
        RoutineInSignalNum = StopRoutine->DcmDspStopRoutineIn->
                RoutineInOutSignalNum;
        for (Index = 0; Index < RoutineInSignalNum; Index++)
        {
            ReqLen = ReqLen + ((uint8)((StopRoutine->DcmDspStopRoutineIn->
                    DcmDspRoutineInOutSignal[Index].DcmDspRoutineSignalLength + 7u) >> 3u));
        }
    }
    else
    {
    	ReqLen = 0;
    }
    if (StopRoutine->DcmDspStopRoutineOut != NULL_PTR)
    {
        RoutineOutSignalNum = StopRoutine->DcmDspStopRoutineOut->
                RoutineInOutSignalNum;
        for (Index = 0; Index < RoutineOutSignalNum; Index++)
        {
            ResLen = ResLen + ((uint8)((StopRoutine->DcmDspStopRoutineOut->
                    DcmDspRoutineInOutSignal[Index].DcmDspRoutineSignalLength + 7u) >> 3u));
        }
    }
    else
    {
    	ResLen = 0;
    }

	if ((ReqLen + DCM_UDS0X31_REQ_DATA_MINLENGTH)
			!= ((uint8)Dcm_MsgCtrl[MsgCtrlId].MsgContext.ReqDataLen))
	{
		/*the request message length is not correct,send NRC 0x13*/
		*ErrorCode  = DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT;
		*Ret = E_NOT_OK;
		return ResLen;
	}

	StopRoutineFnc = StopRoutine->DcmDspRoutineStopFnc;
	if (NULL_PTR == StopRoutineFnc)
	{
		/*StopRoutineFnc is NULL,send NRC 0x31*/
		*ErrorCode  = DCM_E_REQUESTOUTOFRANGE;
		*Ret = E_NOT_OK;
		return ResLen;
	}

	if (DCM_DSP_ROUTINE_ON != Dcm_RoutineControlState[RoutineCfgId])
	{
		/*the request sequence error,send NRC 0x24*/
		*ErrorCode  = DCM_E_REQUESTSEQUENCEERROR;
		*Ret = E_NOT_OK;
		return ResLen;
	}

	pInbuffer  = NULL_PTR;
	if(0u != ReqLen)
	{
		pInbuffer  = &Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[4];
	}
	pOutBuffer = NULL_PTR;
	if(0u != ResLen)
	{
		pOutBuffer = &Dcm_Channel[Offset + 4u];
	}
	*Ret = (*StopRoutineFnc)(pInbuffer,pOutBuffer,ErrorCode);
	if (E_OK == *Ret)
	{
		Dcm_RoutineControlState[RoutineCfgId] = DCM_DSP_ROUTINE_OFF;
	}

	return ResLen;
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"
#endif

/********************************/
#if(STD_ON == DCM_DSP_ROUTINE_FUNC_ENABLED)
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(uint8, DCM_CODE)Dcm_UdsRCReqRoutineResult(
		uint8   MsgCtrlId,
		uint8   RoutineCfgId,
		uint16  Offset,
		P2VAR(Std_ReturnType, AUTOMATIC, AUTOMATIC) Ret,
		P2VAR(Dcm_NegativeResponseCodeType, AUTOMATIC, AUTOMATIC) ErrorCode)
{
	uint8   ResLen = 0;
	uint8   RoutineOutSignalNum;
	uint8   Index;
	P2CONST(Dcm_DspRequestRoutineResultsType,TYPEDEF,DCM_CONST)  RequestRoutineResults;
	Dcm_RequestResultsRoutineFncType  RequestResultsFnc;
	P2VAR(uint8 ,AUTOMATIC ,DCM_VAR_NOINIT) pOutBuffer;

    RequestRoutineResults = Dcm_DspCfg.pDcmDspRoutine[RoutineCfgId].DcmDspRequestRoutineResults;
    if (NULL_PTR == RequestRoutineResults)
    {
        *ErrorCode  = DCM_E_SUBFUNCTIONNOTSUPPORTED;
        *Ret = E_NOT_OK;
        return ResLen;
    }

    if (DCM_UDS0X31_REQ_DATA_MINLENGTH != Dcm_MsgCtrl[MsgCtrlId].MsgContext.ReqDataLen)
    {
        /*the request message length is not correct,send NRC 0x13*/
        *ErrorCode  = DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT;
        *Ret = E_NOT_OK;
        return ResLen;
    }

	RequestResultsFnc = RequestRoutineResults->DcmDspRequestResultsRoutineFnc;
	if (NULL_PTR == RequestResultsFnc)
	{
		*ErrorCode  = DCM_E_REQUESTOUTOFRANGE;
		*Ret = E_NOT_OK;
		return ResLen;
	}

	if (DCM_DSP_ROUTINE_INIT == Dcm_RoutineControlState[RoutineCfgId])
	{
		/*the request sequence error,send NRC 0x24*/
		*ErrorCode  = DCM_E_REQUESTSEQUENCEERROR;
		*Ret = E_NOT_OK;
		return ResLen;
	}

	if (RequestRoutineResults->DcmDspRequestRoutineResultsOut != NULL_PTR)
	{
		RoutineOutSignalNum = RequestRoutineResults->DcmDspRequestRoutineResultsOut->
				RoutineInOutSignalNum;
		for (Index = 0; Index < RoutineOutSignalNum; Index++)
		{
			ResLen = ResLen + ((uint8)((RequestRoutineResults->DcmDspRequestRoutineResultsOut->
					DcmDspRoutineInOutSignal[Index].DcmDspRoutineSignalLength + 7u) >> 3u));
		}
	}
	else
	{
		ResLen = 0;
	}

	pOutBuffer = NULL_PTR;
	if (0u != ResLen)
	{
		pOutBuffer = &Dcm_Channel[Offset + 4u];
	}
	*Ret = (*RequestResultsFnc)(pOutBuffer, ErrorCode);

	return ResLen;
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"
#endif

/********************************/
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
static FUNC(void, DCM_CODE)Dcm_UdsRCSendMsg(
		uint8   ProtocolCtrlId,
		uint8   MsgCtrlId,
		uint8   ResLen,
		uint16  routineId,
		uint16  Offset,
		uint8   SubFunction,
		Std_ReturnType  Ret,
		Dcm_NegativeResponseCodeType  ErrorCode)
{
	/*check the return value*/
	switch (Ret)
	{
		case  E_OK:
			SchM_Enter_Dcm(Dcm_MsgCtrl);
			Dcm_Channel[Offset] = 0x71;
			Dcm_Channel[Offset + 1u] = SubFunction;
			Dcm_Channel[Offset + 2u] = (uint8)(routineId >> 8u);
			Dcm_Channel[Offset + 3u] = (uint8)(routineId);
			Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResMaxDataLen = (uint32)ResLen + 4u;
			Dcm_MsgCtrl[MsgCtrlId].MsgContext.ResDataLen    = (uint32)ResLen + 4u;
			Dcm_MsgCtrl[MsgCtrlId].MsgContext.pResData      = &Dcm_Channel[Offset];
			SchM_Exit_Dcm(Dcm_MsgCtrl);
			DsdInternal_ProcessingDone(ProtocolCtrlId);
			break;
		case  E_NOT_OK:
			/*NRC=ErrorCode*/
			(void)DsdInternal_SetNrc(ProtocolCtrlId, ErrorCode);
			DsdInternal_ProcessingDone(ProtocolCtrlId);
			break;
		case  DCM_E_PENDING:
			Dcm_MsgCtrl[MsgCtrlId].Dcm_OpStatus = DCM_PENDING;
			break;
#if(STD_ON == DCM_DSLDIAGRESP_FORCERESPENDEN)
		case  DCM_E_FORCE_RCRRP:
			Dcm_MsgCtrl[MsgCtrlId].Dcm_Ret = DCM_E_FORCE_RCRRP;
			(void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_RESPONSE_PENDING);
			DsdInternal_ProcessingDone(ProtocolCtrlId);
			break;
#endif
		default:
			/*unexpected return value,send NRC 0x22*/
			(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_CONDITIONSNOTCORRECT);
			DsdInternal_ProcessingDone(ProtocolCtrlId);
		break;
	}

}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"
/********************************/
#define DCM_START_SEC_CODE
#include "Dcm_MemMap.h"
FUNC(Std_ReturnType, DCM_CODE)Dcm_UDS0x31(
		Dcm_OpStatusType OpStatus,
		uint8  ProtocolCtrlId,
		P2VAR(Dcm_NegativeResponseCodeType,AUTOMATIC,DCM_VAR) ErrorCode)
{
	uint8   MsgCtrlId;
	#if((STD_ON == DCM_DSP_ROUTINE_FUNC_ENABLED) && (DCM_DSP_ROUTINE_MAX_NUM > 0))
	uint8   Index;
	uint8   ResLen;
	uint8   SubFunction;
	uint8   RoutineCfgId;
	uint8   TxChannelCtrlIndex;
	uint8   TxChannelCfgIndex;
	uint16  routineId;
	uint16  Offset;
	boolean Flag;
	#endif
	Std_ReturnType  Ret;

    /*************************************************/
    Ret = Dcm_RCConditonCheck(ProtocolCtrlId);
    if(E_OK != Ret)
    {
        return Ret;
    }

	/*check the massage length*/
	MsgCtrlId = Dcm_ProtocolCtrl[ProtocolCtrlId].MsgCtrlIndex;
	if (Dcm_MsgCtrl[MsgCtrlId].MsgContext.ReqDataLen < DCM_UDS0X31_REQ_DATA_MINLENGTH)
	{
		/*the length of massage is not correct,send NRC 0x13*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId, DCM_E_INCORRECTMESSAGELENGTHORINVALIDFORMAT);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}

	/*************************************************/


#if ((STD_OFF == DCM_DSP_ROUTINE_FUNC_ENABLED) || (DCM_DSP_ROUTINE_MAX_NUM == 0))
	/*NRC 0x31:request out of range*/
	(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_REQUESTOUTOFRANGE);
	DsdInternal_ProcessingDone(ProtocolCtrlId);
	return E_NOT_OK;

#else
	/*************************************************/
	/*find the required RoutineID in configuration*/
	routineId =  (uint16)((uint16)((uint16)Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[2]) << 8u)\
			   | ((uint16) Dcm_MsgCtrl[MsgCtrlId].MsgContext.pReqData[3]);
	Flag = FALSE;
	for (Index=0;(Index<Dcm_DspCfg.DcmDspRoutineNum)&&(FALSE == Flag);Index++)
	{
		if ((routineId == Dcm_DspCfg.pDcmDspRoutine[Index].DcmDspRoutineId)
			&&(TRUE == Dcm_DspCfg.pDcmDspRoutine[Index].DcmDspRoutineUsed))
		{
			Flag = TRUE;
		}
	}
	if (FALSE == Flag)
	{
		/*if not found,send NRC 0x31*/
		(void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_REQUESTOUTOFRANGE);
		DsdInternal_ProcessingDone(ProtocolCtrlId);
		return E_NOT_OK;
	}

	/*************************************************/
	/*check session and security*/
	RoutineCfgId     = Index - 1u;

	Ret = Dcm_UdsRCSesAndSecCheck(ProtocolCtrlId, RoutineCfgId);
	if(E_OK != Ret)
	{
		return Ret;
	}

    /*check whether the sub-function is supported*/
    SubFunction = Dcm_MsgCtrl[MsgCtrlId].Subfunction;
    if(  (SubFunction != DCM_UDS0X31_STARTROUTINE)
            && (SubFunction != DCM_UDS0X31_STOPROUTINE)
            && (SubFunction != DCM_UDS0X31_REQUESTROUTINERESULTS) )
    {
        /*if the required sub-function is not supported,send NRC 0x12*/
        (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_SUBFUNCTIONNOTSUPPORTED);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }

	/*************************************************/
	/*get the Tx buffer*/
	TxChannelCtrlIndex = Dcm_MsgCtrl[MsgCtrlId].Dcm_TxCtrlChannelIndex;
	TxChannelCfgIndex  = Dcm_ChannelCtrl[TxChannelCtrlIndex].Dcm_ChannelCfgIndex;
	Offset = (Dcm_DslCfg.pDcmChannelCfg)[TxChannelCfgIndex].offset;
	switch (SubFunction)
	{
		case  DCM_UDS0X31_STARTROUTINE:
			ResLen = Dcm_UdsRCStartRoutine(MsgCtrlId, RoutineCfgId, Offset, &Ret, ErrorCode);
			break;
		case  DCM_UDS0X31_STOPROUTINE:
			ResLen = Dcm_UdsRCStopRoutine(MsgCtrlId, RoutineCfgId, Offset, &Ret, ErrorCode);
			break;
		case  DCM_UDS0X31_REQUESTROUTINERESULTS:
			ResLen = Dcm_UdsRCReqRoutineResult(MsgCtrlId, RoutineCfgId, Offset, &Ret, ErrorCode);
			break;
		default:
			*ErrorCode  = DCM_E_SUBFUNCTIONNOTSUPPORTED;
			Ret = E_NOT_OK;
			break;
	}
    /* check tx data length */
    if((uint16)((uint16)ResLen + 4u) > (Dcm_DslCfg.pDcmChannelCfg[TxChannelCfgIndex].Dcm_DslBufferSize))
    {
        /*Pdu length is bigger than buffer size,ignore the request message */
        (void)DsdInternal_SetNrc(ProtocolCtrlId,DCM_E_RESPONSETOOLONG);
        DsdInternal_ProcessingDone(ProtocolCtrlId);
        return E_NOT_OK;
    }
	/*check the return value*/
	Dcm_UdsRCSendMsg(ProtocolCtrlId, MsgCtrlId, ResLen, routineId, Offset, SubFunction, Ret, *ErrorCode);

	return (Ret);
#endif
}
#define DCM_STOP_SEC_CODE
#include "Dcm_MemMap.h"
#endif
